package ac.svn.accesscontrol.controller;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

import ac.notification.event.INotificationListener;
import ac.notification.event.NotificationEvent;
import ac.notification.manager.NotificationRegistrar;
import ac.svn.accesscontrol.context.Context;
import ac.svn.accesscontrol.context.IContextConstants;
import ac.svn.accesscontrol.manager.SVNInfoManager;
import ac.svn.accesscontrol.store.IConstants;
import ac.svn.accesscontrol.store.IResources;
import ac.svn.accesscontrol.store.ISVNIdentifier;
import ac.svn.accesscontrol.store.ISVNItem;
import ac.svn.accesscontrol.store.SVNGroup;
import ac.svn.accesscontrol.store.SVNLocation;
import ac.svn.accesscontrol.store.SVNUser;
import ac.svn.accesscontrol.ui.ApplicationPopup;
import ac.svn.accesscontrol.utils.Utility;

public class ApplcationPopupController implements INotificationListener,
ISVNIdentifier,IConstants,IResources {

	public enum EventType
	{
		ADD,
		DELETE,
		EDIT,
		CHANGE_ID,
		ACCESS,
		PASSWORD,
		NONE
	}

	private ApplicationPopup  applicationPopup;
	private JMenu addM;
	private JMenuItem addUMI, addGMI, addMI, editMI, deleteMI,changeIdMI, accessIdMI,noSelectionMI,changePasswordMI;
	private Component targetComponent;
	private String eventType;	

	public ApplcationPopupController() 
	{
		initComponents();
		NotificationRegistrar.registerListener(this);
	}
	private void initComponents() 
	{
		applicationPopup = new ApplicationPopup("Application Popup");

		addMI = new JMenuItem("Add",Utility.getImageIcon(LOC_ICN_COMMON_ADD_S));
		addMI.addActionListener(new MenuItemActionListener(EventType.ADD));

		editMI = new JMenuItem("Edit",Utility.getImageIcon(LOC_ICN_COMMON_EDIT_S));
		editMI.addActionListener(new MenuItemActionListener(EventType.EDIT));

		deleteMI = new JMenuItem("Delete",Utility.getImageIcon(LOC_ICN_COMMON_DELETE_S));
		deleteMI.addActionListener(new MenuItemActionListener(EventType.DELETE));

		changeIdMI = new JMenuItem("Change Identifier",Utility.getImageIcon(LOC_ICN_ID_SMALL));
		changeIdMI.addActionListener(new MenuItemActionListener(EventType.CHANGE_ID));

		accessIdMI = new JMenuItem("Change Access Rights",Utility.getImageIcon(LOC_ICN_ACCESS_SMALL));
		accessIdMI.addActionListener(new MenuItemActionListener(EventType.ACCESS));

		changePasswordMI = new JMenuItem("Change password",Utility.getImageIcon(LOC_ICN_PWD_SMALL));
		changePasswordMI.addActionListener(new MenuItemActionListener(EventType.PASSWORD));

		noSelectionMI = new JMenuItem("No Selection");

		addM = new JMenu("Add");
		addUMI = new JMenuItem("User");
		addGMI = new JMenuItem("Group");
		addM.add(addUMI);
		addM.add(addGMI);

		addUMI.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				eventType = VALUE_POPUP_TYPE_USER;
				fireEvent(EventType.ADD);
			}
		});
		addGMI.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				eventType = VALUE_POPUP_TYPE_GROUP;
				fireEvent(EventType.ADD);
			}
		});

		applicationPopup.add(noSelectionMI);
	}

	@Override
	public Set<String> declaredSubscriptionSet() {
		Set<String> subscriptions = new HashSet<String>();
		subscriptions.add(CMD_SHOW_POPUP);		
		return subscriptions;
	}
	@Override
	public void receiveEvent(NotificationEvent notificationEvent) 
	{
		final String neId = notificationEvent.getPropertyIdentifier();
		if(neId.contains(CMD_SHOW_POPUP))
		{
			showPopupHandler(notificationEvent);			
		}
	}

	private void showPopupHandler(NotificationEvent notificationEvent) 
	{
		applicationPopup.removeAll();
		
		eventType	  						= (String) notificationEvent.getParameter(IConstants.KEY_POPUP_TYPE); 	
		MouseEvent event 			= (MouseEvent) notificationEvent.getParameter(IConstants.KEY_POPUP_EVENT);
		targetComponent 				= (Component) notificationEvent.getParameter(IConstants.KEY_POPUP_SOURCE);

		Object[] sel = null;

		if(targetComponent instanceof JList)
		{
			JList targetComp = (JList) targetComponent;
			sel = targetComp.getSelectedValues();			
		}
		else if (targetComponent instanceof JTree)
		{
			JTree tree = (JTree) targetComponent;
			sel = tree.getSelectionPaths();
		}	

		if(null == sel)
		{
			noSelectionMI.setText("No Selection!");
			applicationPopup.add(noSelectionMI);
		}
		else if(1 != sel.length)
		{
			noSelectionMI.setText("Make Single selection!");
			applicationPopup.add(noSelectionMI);
		}
		else		
		{
			loadMenuItems(eventType);
		}

		applicationPopup.show(targetComponent, event.getX(), event.getY());
	}

	private void loadMenuItems(String type) 
	{
		if(VALUE_POPUP_TYPE_GROUP_USER.equalsIgnoreCase(type))
		{
			applicationPopup.add(addM);
		}
		else
		{
			applicationPopup.add(addMI);
		}
		applicationPopup.addSeparator();

		//Essential menu items
		applicationPopup.add(editMI);
		applicationPopup.add(deleteMI);
		applicationPopup.add(changeIdMI);

		//check if location is selected add menu to changes access rights..
		if(IConstants.VALUE_POPUP_TYPE_LOCATION.equalsIgnoreCase(type))
		{
			applicationPopup.addSeparator();
			applicationPopup.add(accessIdMI);
		}

		//If Item is User add menu for Changing password.
		if(IConstants.VALUE_POPUP_TYPE_USER.equalsIgnoreCase(type)
				||
				VALUE_POPUP_TYPE_GROUP_USER.equalsIgnoreCase(type))
		{
			applicationPopup.addSeparator();
			applicationPopup.add(changePasswordMI);
		}


	}

	public class MenuItemActionListener implements ActionListener
	{
		private EventType eventType = EventType.NONE; 

		public MenuItemActionListener(EventType eventType)
		{
			this.eventType = eventType;
		}

		@Override
		public void actionPerformed(ActionEvent e) 
		{
			fireEvent(eventType);
		}
	}

	public void fireEvent(EventType eType) 
	{
		if(EventType.NONE != eType)
		{
			switch (eType)
			{
			case ADD:
				handleAddEvent();
				break;
			case EDIT:
				handleEditEvent();
				break;
			case DELETE:
				handleDeleteEvent();
				break;
			case ACCESS:
				handleAccessChange();
				break;
			case CHANGE_ID:
				handleIdentifierChange();
				break;
			case PASSWORD:
				handlePasswordChange();
				break;
			default:
				break;
			}
		}
	}


	private void handlePasswordChange() 
	{
		if(null != eventType)
		{
			Object selObject = null;
			if(targetComponent instanceof JList)
			{
				selObject = ((JList)targetComponent).getSelectedValue();				
			}
			else if(targetComponent instanceof JTree)
			{
				JTree tree = (JTree) targetComponent;
				TreePath treePath = tree.getSelectionPath();

				if(null != treePath)
				{
					DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
					if(null != node)
					{
						selObject = node.getUserObject();
					}
				}
			}			

			if(null != selObject)
			{
				NotificationEvent event = new NotificationEvent(CMD_CHANGE_PASSWORD);
				event.setPropertyValue(selObject);
				NotificationRegistrar.dispatchNotification(event);
			}
		}
	}
	private void handleIdentifierChange()
	{
		if(null != eventType)
		{
			if(targetComponent instanceof JList)
			{
				Object selObject = ((JList)targetComponent).getSelectedValue();
				if(null != selObject)
				{
					NotificationEvent event = new NotificationEvent(CMD_CHANGE_IDENTIFIER);
					event.setPropertyValue(selObject);
					NotificationRegistrar.dispatchNotification(event);
				}
			}
			else if(targetComponent instanceof JTree)
			{
				JTree tree = (JTree) targetComponent;
				TreePath treePath = tree.getSelectionPath();

				if(null != treePath)
				{
					DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
					if(null != node)
					{
						Object userObject = node.getUserObject();
						NotificationEvent event = new NotificationEvent(CMD_CHANGE_IDENTIFIER);
						event.setPropertyValue(userObject);
						NotificationRegistrar.dispatchNotification(event);
					}
				}
			}
		}
	}


	private void handleAccessChange() 
	{
		if(targetComponent instanceof JList)
		{
			Object selObject = ((JList)targetComponent).getSelectedValue();
			if(null != selObject)
			{
				if(selObject instanceof SVNLocation)
				{
					SVNLocation location = (SVNLocation) selObject;
					Context context = new Context("AccessRightUpdate");
					context.put(IContextConstants.KEY_OPERATION_TYPE, IContextConstants.VALUE_OP_TYPE_EDITING);
					context.put(IContextConstants.KEY_OPERATION_PARAM, location);
					Utility.sendNotification(CMD_MODIFY_ACCESS_RIGHTS, context);
				}
			}
		}
	}
	private void handleDeleteEvent() 
	{
		if(null != eventType)
		{
			if(targetComponent instanceof JList)
			{
				Object selObject = ((JList)targetComponent).getSelectedValue();
				if(null != selObject)
				{
					String cmdId = null;
					if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_USER))
					{
						cmdId = CMD_DELETE_USER;
					}
					else if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_GROUP))
					{
						cmdId = CMD_DELETE_GROUP;
					}
					else if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_LOCATION))
					{
						cmdId = CMD_DELETE_LOCATION;
					}
					NotificationEvent event = new NotificationEvent(cmdId);
					event.setPropertyValue(selObject);
					event.addParameter(P_LOCATION, selObject);
					event.addParameter(P_AUTOMATIC, true);
					NotificationRegistrar.dispatchNotification(event);

				}
			}
			else if(targetComponent instanceof JTree)
			{
				JTree tree = (JTree) targetComponent;
				TreePath treePath = tree.getSelectionPath();

				if(null != treePath)
				{
					DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
					if(null != node)
					{
						Object userObject = node.getUserObject();
						String cmdId = null;
						if(userObject instanceof SVNUser)
						{
							SVNUser user = (SVNUser) userObject;
							userObject = SVNInfoManager.getInfoManager().getSvnUser(user.getId());
							cmdId = CMD_DELETE_USER;
						}
						else if(userObject instanceof SVNGroup)
						{
							SVNGroup group = (SVNGroup) userObject;
							userObject = SVNInfoManager.getInfoManager().getGroup(group.getId());
							cmdId = CMD_DELETE_GROUP;
						}

						NotificationEvent event = new NotificationEvent(cmdId);
						event.setPropertyValue(userObject);
						event.addParameter(P_LOCATION, userObject);
						event.addParameter(P_AUTOMATIC, true);
						NotificationRegistrar.dispatchNotification(event);
					}
				}
			}
		}
	}
	private void handleAddEvent()
	{
		if(null != eventType)
		{
			String cmdId = null;

			if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_USER))
			{
				cmdId = CMD_CREATE_NEW_USER;
			}
			else if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_GROUP))
			{
				cmdId = CMD_ADD_GROUP;
			}
			else if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_LOCATION))
			{
				cmdId = CMD_ADD_LOCATION;
			}
			Utility.sendNotification(cmdId);
		}
	}

	private void handleEditEvent()
	{
		if(null != targetComponent)
		{
			if(targetComponent instanceof JList)
			{
				JList list = (JList) targetComponent;
				ISVNItem iselItem = (ISVNItem) list.getSelectedValue();

				if(null != iselItem)
				{
					String cmdId = null;

					if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_USER))
					{
						cmdId = CMD_EDIT_USER;
					}
					else if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_GROUP))
					{
						cmdId = CMD_EDIT_GROUP;
					}
					else if(eventType.equalsIgnoreCase(VALUE_POPUP_TYPE_LOCATION))
					{
						cmdId = CMD_EDIT_LOCATION;
					}

					NotificationEvent notificationEvent = new NotificationEvent(cmdId);
					notificationEvent.setPropertyValue(iselItem);
					notificationEvent.addParameter(P_LOCATION, iselItem);
					notificationEvent.addParameter(P_AUTOMATIC, Boolean.TRUE);
					NotificationRegistrar.dispatchNotification(notificationEvent);

				}
			}
			else if(targetComponent instanceof JTree)
			{
				JTree tree = (JTree) targetComponent;
				TreePath treePath = tree.getSelectionPath();

				if(null != treePath)
				{
					DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
					if(null != node)
					{
						Object userObject = node.getUserObject();

						NotificationEvent notificationEvent = null;
						if(userObject instanceof SVNGroup)
						{
							notificationEvent = new NotificationEvent(CMD_EDIT_GROUP);
							notificationEvent.setPropertyValue(userObject);
						}
						else if(userObject instanceof SVNUser)
						{
							notificationEvent = new NotificationEvent(CMD_EDIT_USER);
							notificationEvent.setPropertyValue(userObject);
						}		

						if(null != notificationEvent)
						{
							NotificationRegistrar.dispatchNotification(notificationEvent);
						}
					}
				}
			}
		}
	}




}
